home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / ppmtoxpm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-06  |  6.9 KB  |  240 lines

  1. /* ppmtoxpm.c - read a portable pixmap and produce a X11 pixmap
  2. **
  3. ** Copyright (C) 1990 by Mark W. Snitily
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. **
  12. ** This tool was developed for Schlumberger Technologies, ATE Division, and
  13. ** with their permission is being made available to the public with the above
  14. ** copyright notice and permission notice.
  15. */
  16.  
  17. #include <ctype.h>
  18. #include "ppm.h"
  19. #include "ppmcmap.h"
  20.  
  21. /* Max number of colors allowed in ppm input. */
  22. #define MAXCOLORS 256
  23.  
  24. /* Lower bound and upper bound of character-pixels printed in XPM output. */
  25. #define LOW_CHAR '`'
  26. #define HIGH_CHAR '~'
  27.  
  28. typedef struct {    /* character-pixel mapping */
  29.     char* cixel;    /* character string printed for pixel */
  30.     char* rgbname;    /* ascii rgb color, either mnemonic or #rgb value */
  31.     } cixel_map;
  32.  
  33. static char* gen_numstr ARGS(( int i, int base, char low_char, int digits ));
  34. static void gen_cmap ARGS(( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP ));
  35.  
  36. void
  37. main( argc, argv )
  38.     int argc;
  39.     char* argv[];
  40.     {
  41.     FILE* ifp;
  42.     pixel** pixels;
  43.     register pixel* pP;
  44.     int argn, rows, cols, ncolors, row, col, i;
  45.     pixval maxval;
  46.     colorhash_table cht;
  47.     colorhist_vector chv;
  48.     cixel_map cmap[MAXCOLORS];
  49.     int charspp;
  50.     char out_name[100];
  51.     char* cp;
  52.     char* usage = "[-name <xpmname>] [ppmfile]";
  53.  
  54.     ppm_init( &argc, argv );
  55.     out_name[0] = '\0';
  56.  
  57.     argn = 1;
  58.  
  59.     /* Check for command line options. */
  60.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  61.     {
  62.     if ( pm_keymatch( argv[argn], "-name", 2 ) )
  63.         {
  64.         ++argn;
  65.         if ( argn == argc )
  66.         pm_usage( usage );
  67.         (void) strcpy( out_name, argv[argn] );
  68.         }
  69.     else
  70.         pm_usage( usage );
  71.     ++argn;
  72.     }
  73.  
  74.     if ( argn != argc )
  75.     {
  76.     /* Open the input file. */
  77.     ifp = pm_openr( argv[argn] );
  78.  
  79.     /* If output filename not specified, use input filename as default. */
  80.     if ( out_name[0] == '\0' )
  81.         {
  82.         (void) strcpy( out_name, argv[argn] );
  83.         cp = index( out_name, '.' );
  84.         if ( cp != 0 )
  85.         *cp = '\0';    /* remove extension */
  86.         if ( strcmp( out_name, "-" ) == 0 )
  87.         (void) strcpy( out_name, "noname" );
  88.         }
  89.  
  90.     ++argn;
  91.     }
  92.     else
  93.     {
  94.     /* No input file specified. */
  95.     ifp = stdin;
  96.     if ( out_name[0] == '\0' )
  97.         (void) strcpy( out_name, "noname" );
  98.     }
  99.  
  100.     if ( argn != argc )
  101.     pm_usage( usage );
  102.  
  103.     /* Read in the ppm file. */
  104.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  105.     pm_close( ifp );
  106.  
  107.     /* Figure out the colormap. */
  108.     pm_message( "computing colormap..." );
  109.     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
  110.     if ( chv == (colorhist_vector) 0 )
  111.     pm_error(
  112.         "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  113.     pm_message( "%d colors found", ncolors );
  114.  
  115.     /* Make a hash table for fast color lookup. */
  116.     cht = ppm_colorhisttocolorhash( chv, ncolors );
  117.  
  118.     /* Now generate the character-pixel colormap table. */
  119.     gen_cmap( chv, ncolors, maxval, cmap, &charspp );
  120.  
  121.     /* Write out the XPM header. */
  122.     fprintf (stdout,  "#define %s_format %d\n", out_name, 1 );
  123.     fprintf (stdout,  "#define %s_width  %d\n", out_name, cols );
  124.     fprintf (stdout,  "#define %s_height %d\n", out_name, rows );
  125.     fprintf (stdout,  "#define %s_ncolors %d\n", out_name, ncolors );
  126.     fprintf (stdout,  "#define %s_chars_per_pixel %d\n", out_name, charspp );
  127.  
  128.     /* Write out the ascii colormap. */
  129.     fprintf (stdout,  "static char *%s_colors[] = {\n", out_name );
  130.     for ( i = 0; i < ncolors; ++i )
  131.     {
  132.     fprintf (stdout,  "   \"%s\", \"%s\"", cmap[i].cixel, cmap[i].rgbname );
  133.     if ( i != ncolors - 1 )
  134.         fprintf (stdout,  ",\n" );
  135.     else
  136.         fprintf (stdout,  "\n" );
  137.     }     
  138.     fprintf (stdout,  "};\n" );
  139.  
  140.     /* Write out the ascii character-pixel image. */
  141.     fprintf (stdout,  "static char *%s_pixels[] = {\n", out_name );
  142.     for ( row = 0; row < rows; ++row )
  143.     {
  144.     fprintf (stdout,  "\"" );
  145.     for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
  146.         fprintf (stdout,  "%s", cmap[ppm_lookupcolor(cht, pP)].cixel );
  147.     if ( row != rows - 1 )
  148.         fprintf (stdout,  "\",\n" );
  149.     else
  150.         fprintf (stdout,  "\"\n" ); 
  151.     }
  152.     fprintf (stdout,  "};\n" );
  153.  
  154.     pm_close (stdout);
  155.  
  156.     exit( 0 );
  157.     }
  158.  
  159. /* Given a number and a base, this routine prints the number into a
  160. ** malloc'ed string and returns it.  The length of the string is
  161. ** specified by "digits".  The ascii characters of the printed
  162. ** number range from low_char to low_char + base.  The string is
  163. ** low_char filled.
  164. */
  165.  
  166. #if __STDC__
  167. static char*
  168. gen_numstr( int i, int base, char low_char, int digits )
  169. #else /*__STDC__*/
  170. static char*
  171. gen_numstr( i, base, low_char, digits )
  172.     int i, base, digits;
  173.     char low_char;
  174. #endif /*__STDC__*/
  175.     {
  176.     char* str;
  177.     char* p;
  178.     int d;
  179.  
  180.     /* Allocate memory for printed number.  Abort if error. */
  181.     str = (char*) malloc( digits + 1 );
  182.     if ( str == 0 )
  183.     pm_error( "out of memory allocating number string" );
  184.  
  185.     /* Generate characters starting with least significant digit. */
  186.     p = str + digits;
  187.     *p-- = '\0';    /* nul terminate string */
  188.     while ( p >= str )
  189.     {
  190.     d = i % base;
  191.     i /= base;
  192.     *p-- = low_char + d;
  193.     }
  194.  
  195.     return str;
  196.     }
  197.  
  198. #if __STDC__
  199. static void
  200. gen_cmap( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP )
  201. #else /*__STDC__*/
  202. static void
  203. gen_cmap( chv, ncolors, maxval, cmap, charsppP )
  204.     colorhist_vector chv;
  205.     int ncolors;
  206.     pixval maxval;
  207.     cixel_map cmap[MAXCOLORS];
  208.     int* charsppP;
  209. #endif /*__STDC__*/
  210.     {
  211.     int i, j, base;
  212.     char* colorname;
  213.  
  214.     /* Figure out how many characters per pixel we'll be using.  Don't want
  215.     ** to be forced to link with libm.a, so using a division loop rather than
  216.     ** a log function.
  217.     */
  218.     base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
  219.     for ( *charsppP = 0, j = ncolors; j > 0; ++(*charsppP) )
  220.     j /= base;
  221.  
  222.     /* Generate the character-pixel string and the rgb name for each colormap
  223.     ** entry.
  224.     */
  225.     for ( i = 0; i < ncolors; ++i )
  226.     {
  227.     /* Generate color value characters. */
  228.     cmap[i].cixel = gen_numstr( i, base, LOW_CHAR, *charsppP );
  229.  
  230.     /* Generate color name string. */
  231.     colorname = ppm_colorname( &(chv[i].color), maxval, 1 );
  232.  
  233.     /* And copy it. */
  234.     cmap[i].rgbname = (char*) malloc( strlen( colorname ) + 1 );
  235.     if ( cmap[i].rgbname == 0 )
  236.         pm_error( "out of memory allocating color name" );
  237.     (void) strcpy( cmap[i].rgbname, colorname );
  238.     }
  239.     }
  240.